Skip to content

IXR: check if scheme and host keys exist before accessing in IXR_Client and WP_HTTP_IXR_Client#10916

Open
bluefuton wants to merge 4 commits intoWordPress:trunkfrom
bluefuton:fix/ixr-client-host-key-check
Open

IXR: check if scheme and host keys exist before accessing in IXR_Client and WP_HTTP_IXR_Client#10916
bluefuton wants to merge 4 commits intoWordPress:trunkfrom
bluefuton:fix/ixr-client-host-key-check

Conversation

@bluefuton
Copy link

@bluefuton bluefuton commented Feb 12, 2026

Summary

  • IXR_Client accesses $bits['host'] from parse_url() without checking if the key exists, which can trigger an undefined index warning for URLs without a host component (e.g. relative paths).
  • Uses the null coalescing operator (??) to fall back to an empty string, consistent with how port and path are already handled on the adjacent lines.
  • Adds a unit test to verify no error is triggered when the host is missing.

Trac ticket

https://core.trac.wordpress.org/ticket/64635
https://core.trac.wordpress.org/ticket/40784

Test plan

  • Verify IXR_Client no longer triggers an undefined index warning when instantiated with a URL lacking a host component
  • Run npm run test:php -- --filter ixr_client and confirm the tests pass

Drafted Commit Message

XML-RPC: Account for parsed URLs that do not specify host or scheme.

Developed in #10916

Props bluefuton, tfrommen, chrispecoraro, drebbits.web, westonruter.
Fixes #64635, #40784.

`parse_url()` does not always return a `host` key (e.g. for relative
paths). Use the null coalescing operator to fall back to an empty string,
consistent with how `port` and `path` are already handled.

Adds a unit test to verify no error is triggered when the host is missing.

Trac: https://core.trac.wordpress.org/ticket/64635
@github-actions
Copy link

github-actions bot commented Feb 12, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props bluefuton, westonruter, tfrommen.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@westonruter
Copy link
Member

Should the same fix be applied to WP_HTTP_IXR_Client?

$this->scheme = $bits['scheme'];
$this->server = $bits['host'];
$this->port = $bits['port'] ?? $port;
$this->path = ! empty( $bits['path'] ) ? $bits['path'] : '/';

@bluefuton
Copy link
Author

Should the same fix be applied to WP_HTTP_IXR_Client?

Yes, I think so. There's actually an open ticket already for this:

https://core.trac.wordpress.org/ticket/40784

And the suggested patch was:

https://core.trac.wordpress.org/attachment/ticket/40784/40784.diff

Shall I address it in this PR @westonruter?

@westonruter
Copy link
Member

@bluefuton ah, perfect. Yes, could you apply that patch to the PR and update it so we can address both together?

@bluefuton bluefuton force-pushed the fix/ixr-client-host-key-check branch from 5215b3c to ec8d232 Compare February 16, 2026 04:25
bluefuton and others added 2 commits February 16, 2026 17:28
@bluefuton bluefuton force-pushed the fix/ixr-client-host-key-check branch from b4eabf1 to 2413b12 Compare February 16, 2026 04:28
@bluefuton
Copy link
Author

bluefuton commented Feb 16, 2026

Yes, could you apply that patch to the PR and update it so we can address both together?

Added! 👍 I've modernized the original patch (using ?? to be consistent with the surrounding code and assertSame in tests for strict equality).

Sidenote

It looks like at one point IXR_Client was a third-party library by Simon Willison: https://simonwillison.net/2002/Sep/2/aNewXMLRPCLibraryForPHP/. This was back in 2002 and it is not actively maintained any more: https://simonwillison.net/2022/Jun/12/twenty-years/

If we are now treating it as part of WP, we could probably do some further cleanup in there, like dropping PHP4 support.

@bluefuton
Copy link
Author

We should give @tfrommen props for the original patch on #40784 too :)

@westonruter
Copy link
Member

westonruter commented Feb 16, 2026

@bluefuton It seems the only difference between the constructors for the two classes is that WP_HTTP_IXR_Client also sets a scheme. That said, could WP_HTTP_IXR_Client::__construct() be further simplified to just:

	public function __construct( $server, $path = false, $port = false, $timeout = 15 ) {
		parent::__construct( $server, $path, $port, $timeout );
		$this->scheme = parse_url( $server, PHP_URL_SCHEME ) ?? 'http';
	}

@bluefuton
Copy link
Author

It seems the only difference between the constructors for the two classes is that WP_HTTP_IXR_Client also sets a scheme. That said, could WP_HTTP_IXR_Client::__construct() be further simplified

Nice cleanup! There's one subtlety though - the parent IXR_Client::__construct() defaults the port to 80 when parsing a URL, while WP_HTTP_IXR_Client defaults to $port (which is false by default). We'd need to handle that too.

Co-authored-by: Weston Ruter <westonruter@gmail.com>
@tfrommen
Copy link
Member

Hey, nice to see some work on this. 😉

The above suggestion by @westonruter would always default to 'http':

	public function __construct( $server, $path = false, $port = false, $timeout = 15 ) {
		parent::__construct( $server, $path, $port, $timeout );
		$this->scheme = parse_url( $server, PHP_URL_SCHEME ) ?? 'http';
	}

However, the current code only does this (hard-coded) if there was no $path specified.

To keep that behavior, we would need to put the code inside a conditional. Also covering the different handling of the port, this would give us this:

	public function __construct( $server, $path = false, $port = false, $timeout = 15 ) {
		parent::__construct( $server, $path, $port, $timeout );
		if ( ! $path ) {
			$this->scheme = parse_url( $server, PHP_URL_SCHEME ) ?? 'http';
			$this->port   = parse_url( $server, PHP_URL_PORT ) ?? '';
		}
	}

Thoughts?

@bluefuton
Copy link
Author

I know we're a few years on from your original patch @tfrommen! Hope we can get it merged for you 🙂

The refactor to call parent::__construct() would definitely slim things down. It looks like there are a few subtle differences to navigate though, and personally I would choose to land the ?? additions and tests, and consider refactoring in a followup PR.

@bluefuton bluefuton changed the title IXR: check if host key exists before accessing it in IXR_Client IXR: check if scheme and host keys exist before accessing in IXR_Client and WP_HTTP_IXR_Client Feb 18, 2026
@westonruter
Copy link
Member

@bluefuton Sounds good to me.

@tfrommen How do you feel with the PR as it stands? If you approve, I'll proceed with commit.

georgeclapps9-tech

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments